package com.xiyuan.smartutils.template.engine.statement;

import com.xiyuan.smartutils.Types;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.template.engine.StatementParser;
import com.xiyuan.smartutils.template.engine.TagType;
import com.xiyuan.smartutils.template.engine.VariableMap;
import com.xiyuan.smartutils.template.engine.exception.StatementException;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author xiyuan-lgz
 */
@SuppressWarnings({"AlibabaAvoidStartWithDollarAndUnderLineNaming", "AlibabaLowerCamelCaseVariableNaming"})
public class _IF extends Statement {
    private static final long serialVersionUID = 1L;
    private final List<_IF_ELSE_IF> elseIfList = new ArrayList<_IF_ELSE_IF>(0);
    private _IF_ELSE _else;
    
    public _IF(StatementParser statementParser) {
        super(statementParser);
    }
    
    @Override
    public void addStatement(Statement stmt) {
        if (stmt == null) {return;}
        
        if (stmt.getType() == TagType.ELSEIF) {
            stmt.setParent(this);
            elseIfList.add((_IF_ELSE_IF) stmt);
        }
        else if (stmt.getType() == TagType.ELSE) {
            stmt.setParent(this);
            _else = (_IF_ELSE) stmt;
        }
        else {super.addStatement(stmt);}
    }
    
    @Override
    protected void build(VariableMap variableMap, PrintWriter out) {
        if (expressions.isEmpty()) {
            throw new StatementException(getPath(), getLineNo(), getBeginColumn(), getType() + "缺少条件表达式");
        }
        
        Object condition = expressions.get(0).execute(variableMap);
        // 表达式为null表示不检查所有的if,elseif,else，如item.isTrue()时item==null导致方法返回null
        if (condition == null) {return;}
        
        // 不是null，则检查是不是布尔型，如果不是报异常
        if (!Types.isBoolean(condition)) {
            throw new StatementException(getPath(),
                                         getLineNo(),
                                         getBeginColumn(),
                                         getType() + "中表达式" + expressions.get(0) + "，格式不正确，不是布尔型");
        }
        
        // <#if >
        if ((Boolean) condition) {
            if (!hasChild()) {return;}
            
            Statement stmt = null;
            try {
                variableMap.newVariableSpace();// 创建局部变量空间
                
                Iterator<Statement> iterator = childs.iterator();
                while (iterator.hasNext()) {// 循环内容
                    stmt = iterator.next();
                    stmt.execute(variableMap, out);
                }
            }
            finally {
                // 销毁局部变量空间
                variableMap.releaseVariableSpace();
            }
            
            return;
        }
        
        // <#elseif
        for (int i = 0; i < elseIfList.size(); i++) {
            _IF_ELSE_IF elseif = elseIfList.get(i);
            if (elseif.is(variableMap)) {
                elseif.execute(variableMap, out);
                return;
            }
        }
        
        // <#else>
        if (_else != null) {_else.execute(variableMap, out);}
        
    }
    
    @Override
    public TagType getType() {
        return TagType.IF;
    }
    
    @Override
    public boolean parseTag(StatementParser parser) throws StatementException {
        StringBuilder value = new StringBuilder();
        char ch = 0, quote = 0, prvChar = 0;
        int expression_begin_line = 0, expression_begin_column = 0;
        boolean space = false;
        while (parser.hasNext()) {
            prvChar = value.length() == 0 ? 0 : ch;
            ch = parser.next();
            if (value.length() == 0 && Validates.isWhitespace(ch)) {
                space = true;
                continue;
            }
            
            value.append(ch);
            // 只是以#if开头而已
            if (!space) {return false;}
            
            if (value.length() == 1) {
                // 记录表达式开始行列
                expression_begin_line = parser.getLineNum();
                expression_begin_column = parser.getColumn();
            }
            if (quote == 0 && (ch == _QUOTE_ || ch == _DOUBLE_QUOTE_)) {
                // 字符串开始
                quote = ch;
                continue;
            }
            
            if (quote != 0 && ch == quote && prvChar == _BACK_SLASH_) {
                // 字符串结束
                quote = 0;
                continue;
            }
            
            if (quote == 0 && ch == _GATHER_) {// 标签定义完成
                value.setLength(value.length() - 1);
                
                // 标签定义完成
                this.setCompleteTag();
                
                // 解析表达式
                super.parseExpression(expression_begin_line, expression_begin_column, value);
                break;
            }
        }
        
        if (expressions.isEmpty()) {
            throw new StatementException(this.getPath(),
                                         this.getLineNo(),
                                         this.getBeginColumn(),
                                         "文档已结束。" + getType() + "标签 缺少条件表达式定义");
        }
        
        if (!this.isCompleteTag()) {
            throw new StatementException(this.getPath(),
                                         this.getLineNo(),
                                         this.getBeginColumn(),
                                         "文档已结束。" + getType() + "标签定义缺少‘>’");
        }
        
        this.setStatement(this.getStatement() + (expressions.isEmpty()
                                                 ? ""
                                                 : (" " + expressions.get(0))) + getType().getTagComplete());
        return true;
    }
}
